package persistencia;

import gamebook.Partida;
import gamebook.UsuarioGenerico;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class PPartida {

    public static boolean darAltaBD(Partida partida) throws SQLException, Exception {
        boolean resultado = true;         //Si resultado es false es que hubo algún problema
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        //Para el uso de fechas
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        connection = Persistencia_Conexion.getConnection();
        statement = connection.createStatement();
        String query = "INSERT INTO partida(id_retador ,id_retado ,colorRetador ,fechaIni,"
                + "estado ,ganador) values ("
                + "" + partida.getuRetador().getId() + ","
                + "" + partida.getuRetado().getId() + ",'"
                + partida.getColorRetador() + "','"
                + dateFormat.format(partida.getfInicio()) + "',0,0)";

        int registros = statement.executeUpdate(query);
        if (registros == 1) {
            //Si hemos introducido el nuevo mensaje, le asignamos el ID con el que se guardó en la base de datos
            resultSet = statement.executeQuery("select id_partida from partida order by id_partida desc");
            if (resultSet.next()) {
                partida.setIdPartida(resultSet.getInt("id_partida"));
            }
        } else {
            //Si no se ha introducido el nuevo mensaje por alguna causa, asignamos false a resultado
            resultado = false;
        }
        return resultado;
    }

    /**
     * Devuelve de la base de datos el objeto Partida que coincide con el id proporcionado
     * @param id entero id_partida
     * @return devuelve el objeto partida con el id elegido
     */
    public static Partida seleccionarPorIdBD(int id) {
        List<Partida> listPartida = new ArrayList();
        String sql = "SELECT id_partida, id_retador, id_retado, colorRetador, fechaIni, fechaFin, estado, ganador "
                + "FROM partida "
                + "WHERE id_partida=" + id;
        listPartida = seleccionarBD(sql);
        if (listPartida.isEmpty()) {
            return null;
        } else {
            return listPartida.get(0);
        }
    }

    public static List<Partida> seleccionarPorUsuarioGenericoBD(UsuarioGenerico ug, int selector) {
        List<Partida> partidas = new ArrayList<Partida>();
        String sql = "";
        DateFormat dft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (selector == 0) { //DevuelvePartidas sin empezar o en curso
            sql = "select id_partida, id_retador, id_retado, colorRetador, fechaIni, fechaFin, "
                    + "estado, ganador FROM partida WHERE fechaIni<='" + dft.format(new Date()) + "' AND estado<3 "
                    + "AND (id_retador=" + ug.getId() + " OR id_retado=" + ug.getId() + ") order by fechaIni desc";
        } else if (selector == 1) { //Devuelve partidas terminadas
            sql = "select id_partida, id_retador, id_retado, colorRetador, fechaIni, fechaFin, "
                    + "estado, ganador FROM partida WHERE estado=3 "
                    + "AND (id_retador=" + ug.getId() + " OR id_retado=" + ug.getId() + ") order by fechaIni desc";
        }
        partidas = seleccionarBD(sql);
        if (partidas.isEmpty()) {
            return null;
        } else {
            return partidas;
        }
    }

    public static List<Partida> seleccionarBD(String sql) {
        //Lista de MensajesGenericos que devolveremos
        List<Partida> partidas = new ArrayList();

        //Para conectar con la base de datos
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        //Para usar la fecha
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        try {
            //Conectamos con la base de datos
            connection = Persistencia_Conexion.getConnection();
            statement = connection.createStatement();

            resultSet = statement.executeQuery(sql);

            //Mientras haya mensajes que cumplan el criterio SQL los vamos añadiendo
            while (resultSet.next()) {
                //Creamos un mensaje genérico
                Partida partida = new Partida();
                //Ahora si metemos todo lo que sea común a las tres subclase
                partida.setIdPartida(resultSet.getInt("id_partida"));
                partida.setuRetador(UsuarioGenerico.getUsuarioPorId(resultSet.getInt("id_retador")));
                partida.setuRetado(UsuarioGenerico.getUsuarioPorId(resultSet.getInt("id_retado")));
                partida.setColorRetador(resultSet.getString("colorRetador"));
                partida.setfInicio(dateFormat.parse(resultSet.getString("fechaIni")));
                partida.setfFin(dateFormat.parse(resultSet.getString("fechaIni")));
                partida.setEstado(resultSet.getInt("estado"));

                //Agregamos a la lista y cogemos el siguiente si lo hay
                partidas.add(partida);
            }

        } catch (Exception ex) {
            System.out.println(ex.toString());
        } finally {
            try {
                resultSet.close();
                statement.close();
                connection.close();
            } catch (Exception ex) {
                System.out.println(ex.toString());
            }
        }

        return partidas;
    }

    /**
     * Devuelve una lista de String con los movimientos de una partida
     * @param Partida de la que queremos conocer los movimientos
     * @return Lista de String (ArrayList)
     */
    public static List<String> seleccionarMovimientosBD(Partida partida) {
        List<String> listMovimiento = new ArrayList();
        String sql = "SELECT id_mov, id_partida, id_jugador, descripcion "
                + "FROM movimientos "
                + "WHERE id_partida=" + partida.getIdPartida();

        //Para conectar con la base de datos
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
            //Conectamos con la base de datos
            connection = Persistencia_Conexion.getConnection();
            statement = connection.createStatement();
            //Ejecutamos la consulta
            resultSet = statement.executeQuery(sql);

            //Mientras haya movimientos que cumplan el criterio SQL los vamos añadiendo
            while (resultSet.next()) {
                //Agregamos el movimiento a la lista y cogemos el siguiente si lo hay
                listMovimiento.add(resultSet.getString("descripcion"));
            }

        } catch (Exception ex) {
            System.out.println(ex.toString());
        } finally {
            //Cerramos todo
            try {
                resultSet.close();
                statement.close();
                connection.close();
            } catch (Exception ex) {
                System.out.println(ex.toString());
            }
        }

        return listMovimiento;
    }

    public static boolean turno(UsuarioGenerico usuario, Partida partida) {
        boolean turno = false;

        String sql = "SELECT id_mov, id_partida, id_jugador, descripcion "
                + "FROM movimientos "
                + "WHERE id_partida=" + partida.getIdPartida() + " order by id_mov desc limit 0,1";

        //Para conectar con la base de datos
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
            //Conectamos con la base de datos
            connection = Persistencia_Conexion.getConnection();
            statement = connection.createStatement();
            //Ejecutamos la consulta
            resultSet = statement.executeQuery(sql);

            if (resultSet.next()) {
                if (resultSet.getInt("id_jugador") == usuario.getId()) {
                    turno = true;
                }
            } else {
                //Si no hay ningún movimiento para ver a quién le toca: EMPIEZAN BLANCAS
                if (partida.getColorRetador().equals("B")) {//Si el retador Juega Blancas
                    if (usuario.getId() == partida.getuRetador().getId()) {//y el usuario es el retador
                        return false;//le toca a él, así que devolvemos un FALSE
                    } else {
                        return true;//Si el usuario no es el retador, devolvemos TRUE
                    }
                } else {//Si el retador Juega Negras
                    if (usuario.getId() == partida.getuRetador().getId()) {//y el usuario es el retador
                        return true;//No le toca a él, así que devolvemos un TRUE
                    } else {
                        return false;//Si el usuario no es el retador, devolvemos FALSE
                    }
                }
            }

        } catch (Exception ex) {
            System.out.println(ex.toString());
        } finally {
            //Cerramos todo
            try {
                resultSet.close();
                statement.close();
                connection.close();
            } catch (Exception ex) {
                System.out.println(ex.toString());
            }
        }

        return turno;
    }

    /**
     * Introduce un nuevo movimiento en una partida
     * @param Partida de la que queremos conocer los movimientos
     * @return Lista de String (ArrayList)
     */
    public static boolean darAltaMovimientoBD(Partida partida, String movimiento) {
        boolean resultado = false;

        //Obtenemos el ID del jugador que le toca:
        int idJugadorTurno = 0;
        //Si el ultimo turno jugado fue del jugador retador, el id del nuevo movimiento es el del jugador retado
        if (partida.turno(partida.getuRetador())) {
            idJugadorTurno = partida.getuRetado().getId();
        } else { //... y si no... es el otro, el retador
            idJugadorTurno = partida.getuRetador().getId();
        }

        String sql = "INSERT INTO movimientos (id_partida, id_jugador, descripcion) "
                + "VALUES ("
                + partida.getIdPartida() + ", "
                + idJugadorTurno + ", "
                + "'" + movimiento + "'"
                + ")";

        //Para conectar con la base de datos
        Connection connection = null;
        Statement statement = null;
        
        try {
            //Conectamos con la base de datos
            connection = Persistencia_Conexion.getConnection();
            statement = connection.createStatement();
            //Ejecutamos la consulta
            int registros = statement.executeUpdate(sql);

            if (registros == 1) {
                //Si todo ha ido bien, devolvemos un true
                resultado = true;
            } else {
                //Si no se ha introducido el nuevo mensaje por alguna causa, asignamos false a resultado
                resultado = false;
            }
        } catch (Exception ex) {
            //Caso de fallo, resultado es false
            resultado = false;
        } finally {
            //Cerramos todo
            try {
                statement.close();
                connection.close();
            } catch (Exception ex) {
                System.out.println(ex.toString());
            }
        }
        return resultado;
    }

    /*Aceptar un reto que se convierte en una partida*/
    public static void aceptarReto(Partida partida) {
        String sql = "UPDATE partida SET estado=1 "
                + "WHERE id_partida=" + partida.getIdPartida();

        //Para conectar con la base de datos
        Connection connection = null;
        Statement statement = null;

        try {
            //Conectamos con la base de datos
            connection = Persistencia_Conexion.getConnection();
            statement = connection.createStatement();
            //Ejecutamos la consulta
            statement.executeUpdate(sql);

        } catch (Exception ex) {
            System.out.println(ex.toString());
        } finally {
            //Cerramos todo
            try {
                statement.close();
                connection.close();
            } catch (Exception ex) {
                System.out.println(ex.toString());
            }
        }
    }
    /*Aceptar un reto que se convierte en una partida*/

    public static void rechazarReto(Partida partida) {
        String sql = "DELETE from partida "
                + "WHERE id_partida=" + partida.getIdPartida();

        //Para conectar con la base de datos
        Connection connection = null;
        Statement statement = null;

        try {
            //Conectamos con la base de datos
            connection = Persistencia_Conexion.getConnection();
            statement = connection.createStatement();

            statement.executeUpdate(sql);

        } catch (Exception ex) {
            System.out.println(ex.toString());
        } finally {
            //Cerramos todo
            try {
                statement.close();
                connection.close();
            } catch (Exception ex) {
                System.out.println(ex.toString());
            }
        }
    }

    /**
     * Actualiza los datos de una partida en la base de datos
     * @param Partida partida que queremos actualizar con los nuevos datos
     * @return true o false dependiendo de si se cambio algo o no
     */
    public static boolean actualizarBD(Partida partida) {
        boolean resultado = true;         //Si resultado es false es que hubo algún problema
        Connection connection = null;
        Statement statement = null;

        //Para el uso de fechas

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        try {
            //Conexión con la base de datos
            connection = Persistencia_Conexion.getConnection();
            statement = connection.createStatement();

            //El campo de fecha de inicio necesita un tratamiento previo para pasarlo a String
            Date dateInicio = partida.getfInicio();
            String stringInicio = dateFormat.format(dateInicio);

            //El campo de fecha de inicio necesita un tratamiento previo para pasarlo a String
            Date dateFin = partida.getfFin();
            //Este campo podría ser nulo si la partida no ha acabado
            String stringFin = "";
            if (dateFin == null) {
                stringFin = "9999-12-00 00:00:00";
            } else {
                stringFin = dateFormat.format(dateFin);
            }

            //El ganador podría no estar establecido y en ese caso ponemos cero
            int intGanador = 0;
            if (partida.getGanador() != null) {
                //Si hay ganador, ponemos su id
                intGanador = partida.getGanador().getId();
            }

            String sql = "update partida set "
                    + "id_retador=" + partida.getuRetador().getId() + ", "
                    + "id_retado=" + partida.getuRetado().getId() + ", "
                    + "colorRetador='" + partida.getColorRetador() + "', "
                    + "fechaIni='" + stringInicio + "',"
                    + "fechaFin='" + stringFin + "',"
                    + "estado=" + partida.getEstado() + ","
                    + "ganador=" + intGanador + " "
                    + "where id_partida=" + partida.getIdPartida();

            //Pasamos el UPDATE a la base de datos
            int registros = statement.executeUpdate(sql);

            //Verificamos que se haya actualizado UN registro
            if (registros != 1) {
                //Esto puede ser por algún fallo o porque los valores introducidos son iguales a los que había
                resultado = false;
            }

        } catch (Exception ex) {
            //Si hubo error en algun sitio, ponemos resultado a false
            resultado = false;
        } finally {
            //Cerramos todo y salimos
            try {
                statement.close();
                connection.close();
            } catch (Exception ex) {
            }
        }

        return resultado;
    }
}
